﻿using Artech.Common;
using Artech.Common.Properties;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ContainerModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace Artech.Core.Configuration
{
    /// <summary>
    /// This class is used as the base class of all provider based configuration element.
    /// </summary>
    /// <typeparam name="T">The type of provider.</typeparam>
    public abstract class ProviderDataBase<T> : NameTypeConfigurationElement where T:class
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="ProviderDataBase{T}"/> class.
        /// </summary>
        public ProviderDataBase() { }

        /// <summary>
        /// Initializes a new instance of the <see cref="ProviderDataBase{T}"/> class.
        /// </summary>
        /// <param name="type">The type.</param>
        public ProviderDataBase(Type type)
            : base(null, type) { }

        /// <summary>
        /// Initializes a new instance of the <see cref="ProviderDataBase{T}"/> class.
        /// </summary>
        /// <param name="name">The name of the element.</param>
        /// <param name="type">The <see cref="Type" /> that this element is the configuration for.</param>
        public ProviderDataBase(string name, Type type)
            : base(name, type) { }

        /// <summary>
        /// Gets the registrations.
        /// </summary>
        /// <param name="configurationSource">The configuration source.</param>
        /// <param name="defaultProviderName">Default name of the provider.</param>
        /// <returns>The <see cref="TypeRegistration"/> list.</returns>
        public virtual IEnumerable<TypeRegistration> GetRegistrations(IConfigurationSource configurationSource, string defaultProviderName)
        {
            Expression<Func<T>> providerCreation = this.CreateProvider(configurationSource);
            yield return new TypeRegistration(providerCreation, typeof(T))
            {
                Name = this.Name,
                IsDefault = string.Compare(defaultProviderName, this.Name, true) == 0,
                Lifetime = this.LifeTime
            };
        }


        /// <summary>
        /// Creates the provider.
        /// </summary>
        /// <param name="configurationSource">The configuration source.</param>
        /// <returns>The expression to create target provider.</returns>
        /// <exception cref="System.NotImplementedException"></exception>
        protected virtual Expression<Func<T>> CreateProvider(IConfigurationSource configurationSource)
        {
            throw new NotImplementedException(ResourceUtility.Format(GeneralResources.ExceptionMethodMustBeImplementedBySubclasses));
        }

        /// <summary>
        /// Gets the <see cref="TypeRegistrationLifetime"/> of the provider type registration.
        /// </summary>
        /// <value>
        /// The <see cref="TypeRegistrationLifetime"/>  of the provider type registration.
        /// </value>
        /// <remarks>The default value is Singleton.</remarks>
        protected virtual TypeRegistrationLifetime LifeTime
        {
            get { return TypeRegistrationLifetime.Singleton; }
        }
    }
}
